import requests
import re
from datetime import datetime
import math
import random


class MusicDownloader:

    @classmethod
    def getGuid(cls):
        # 获取歌曲的guid
        t = datetime.utcnow().microsecond // 1000
        guid = math.trunc(2147483647 * random.random()) * t % 10000000000
        return guid

    @classmethod
    def getCid(cls):
        # 获得cid
        # 向 https://y.gtimg.cn/music/portal/js/common/map.js 发送请求
        map_url = "https://y.gtimg.cn/music/portal/js/common/map.js"
        response = requests.get(map_url)

        res_str = response.content.decode()
        # 获取"p1:"后的url的值
        p1_url = re.findall(r'"p1":{"url":"(.*?)","deps"', res_str)

        # 向获得的url地址发送请求
        if len(p1_url) > 0:
            p1_url = "https:" + p1_url[0]
            response = requests.get(p1_url)
            res_str = response.content.decode()
            # 使用正则获得cid
            cid = re.findall(r"data:{cid:(\d*?),format", res_str)
            # print(cid)
            if len(cid) > 0:
                cid = cid[0]
                return cid

        raise Exception("获取CID异常")

    @classmethod
    def getVkey(cls, cid, songmid, filename, guid):
        # 获取歌曲的vkey
        vkey_url = "https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg?&platform=yqq&cid={}&songmid={}&filename={}&guid={}"
        vkey_url = vkey_url.format(cid, songmid, filename, guid)
        cookies = {
            "pgv_pvid": str(guid),
        }

        response = requests.get(vkey_url, cookies=cookies)
        res_str = response.content.decode()

        vkey = re.findall(r'"vkey":"(.*?)"', res_str)
        if len(vkey) >0:
            return vkey[0]

        raise Exception("获取Vkey异常")

    @classmethod
    def getMusic(cls, filename, vkey, guid):
        # 获取歌曲
        # http://dl.stream.qqmusic.qq.com/C400000Md1wq0vnwzE.m4a?vkey=4A1B7F433D22D99BF221BAF429EDD4B73D3BCE90C5006C97B9A7B68CE792E61B2AB1C7C66E53C9F2963E6DCA85F82A10FF3CEED7C450D711&guid=4422592355
        song_url = "http://dl.stream.qqmusic.qq.com/{}?vkey={}&guid={}&uin=0&fromtag=6"
        song_url = song_url.format(filename, vkey, guid)

        cookies = {
            "pgv_pvid": str(guid),
        }

        res = requests.get(song_url, cookies=cookies)

        with open(filename, "wb") as f:
            f.write(res.content)
            return 0

        return -1

    @classmethod
    def downloadMusic(cls, songmid):

        # 1、获的cid
        cid = cls.getCid()
        # 2、获得GUID
        guid = cls.getGuid()
        # 3、获得vkey
        filename = "C400{}.m4a".format(songmid)
        vkey = cls.getVkey(cid, songmid, filename, guid)
        # 4、保存歌曲
        res = cls.getMusic(filename, vkey, guid)
        if not res:
            print("保存歌曲成功")

if __name__ == '__main__':
    MusicDownloader.downloadMusic("003vUjJp3QwFcd")